/**
 * 
 * NOTICE -- YOU MUST LEAVE THIS NOTICE IN PLACE.  PER THE TERMS OF THE LICENSE BELOW, YOU MAY SUBLICENSE THIS SOFTWARE 
 * IN ANY WAY THAT DOES NOT CONFLICT WITH THIS LICENSE.
 *
 * Copyright (c) 2011, Paul Gribben <paul.gribben@gmail.com>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the 
 *       documentation and/or other materials provided with the distribution.
 *	
 *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 *	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 *	DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 *	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 *	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 *	OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
package org.softwise.rss2kindle.impl;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import org.softwise.rss2kindle.model.EntryWriter;
import org.softwise.rss2kindle.model.RssAdapter;
import org.softwise.rss2kindle.model.RssEntryTransformer;
import org.softwise.rss2kindle.model.RssEntryTransformer.RssEntry;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;

public class Rss2Html {
	private Stack<String> tagStack = new Stack<String>();
	private Writer writer;

	
	public void generate(String rssURL, String outFilePath) throws Exception {
		generate(rssURL, outFilePath, Integer.MAX_VALUE);
	}
	
	public void generate(String rssURL, String outFilePath, int maxArticles) throws Exception {
		generate(rssURL, new OutputStreamWriter(new FileOutputStream(outFilePath), "UTF-8"), maxArticles);
	}
	
	public void generate(String rssURL, Writer suppliedWriter, int maxArticles) throws Exception {
		writer = suppliedWriter;
		
		try {
			URL feedUrl = new URL(rssURL);
			RssAdapter adapter = FeedWriterFactory.getInstance().getRssAdapter(rssURL);
			EntryWriter entryWriter = adapter.getEntryWriter();
			RssEntryTransformer rssEntryTransformer = adapter.getRssTransformer();
			
			openTag("html");
			openTag("head");
			writer.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/>");
			entryWriter.writeHeaderInfo(writer);
			closeTag(); // head
			
			openTag("body");
			writeTagAndBody("h1", "Table of Contents");
			openTag("ul");
			// http://www.guardian.co.uk/science/rss
			SyndFeedInput input = new SyndFeedInput();
			SyndFeed feed = input.build(new InputStreamReader(feedUrl.openStream(), "UTF-8"));
			List<SyndEntry> list = (List<SyndEntry>)feed.getEntries();
			List<RssEntry> rssList = new ArrayList<RssEntry>();
			
			int entryCount=0;
			
			for (SyndEntry entry : list) {
				RssEntry rssEntry = new RssEntryImpl(entry);
				if (rssEntryTransformer != null) {
					rssList.addAll(rssEntryTransformer.getEntries(rssEntry));
				} else {
					rssList.add(rssEntry);
				}
				if (rssList.size()>=maxArticles) {
					if (rssList.size()>maxArticles) {
						rssList = rssList.subList(0, maxArticles);
					}
					break; // got all the articles we need
				}
			}
			
			for (RssEntry rssEntry : rssList) {				
				openTag("li");
				writeTagAndBody("a href=\"#" + getAnchorId(++entryCount) + '\"', rssEntry.getTitle());
				closeTag();
			}
			closeTag();	// ul
			
			entryCount=0;
			for (RssEntry entry : rssList) {
				openTag("a name=\"" + getAnchorId(++entryCount) + '\"');
				if (entryWriter.isHeadingRepeated()) {
					writeTagAndBody("h3", entry.getTitle());
					closeTag();
				}
				openTag("div");
				entryWriter.write(writer, entry);
				closeTag(); // div
			}
			
			closeTag();	// body
			closeTag();	// html
		} finally {
			writer.flush();
			writer.close();
		}
	}

	private String getAnchorId(int val) {
		return "a" + val;
	}
	
	private void openTag(String tagName) throws IOException {
		int spaceIdx = tagName.indexOf(' ');
		tagStack.push(spaceIdx>1 ? tagName.substring(0, spaceIdx) : tagName);
		writer.write('<' + tagName + '>');		
	}
	
	private void closeTag() throws IOException {
		writer.write("</" + tagStack.pop() + '>');		
	}
	
	private void writeTagAndBody(String tagName, String body) throws IOException {
		openTag(tagName);
		writer.write(body);
		closeTag();
	}	
}
